iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
自我挑戰組

邊工作邊進行前端學習之旅系列 第 28

[Day 28] JS實作練習 - Scroll Blog無限捲動

  • 分享至 

  • xImage
  •  

前言

有注意到每次實作練習的最前面都會有個-觀察功能需求項目嗎?這是在饅頭計畫中老師特別強調要拉出來製作的部分,後來看其他技術文或是六角學院課程也會提到這部分的重要性,在開始一個作品前,都要先去了解要製作哪些項目,將它拆解,並大約知道可以用什麼方式來製作,可以快速進入狀況、減少緊張感並依據整理出的項目一項項完成,即便中斷也能快速銜接上未完成的部分。

課程連結
成品

觀察功能需求

1.隨著頁面的往下捲動,會載入新的資料

  • 一開始頁面載入,會呈現5筆資料,捲動往下,會再載入5筆
  • 使用{JSON} Placeholder的資料來串接(運用ajax)
  • 設定捲動位置,並於該位置時,會呈現載入的圖示
  • setTimeout來呈現載入的時間與畫面

2.網頁的各資料是有順序,資料左上會有編碼

  • 利用資料本身的id作為序號
  • 於JS時,帶入該變數取值

各項拆解說明

1.API資料來源:

2.使用ajax串接API

  • Async/Await 非同步流程控制-筆記
  • 參考Using async await with jQuery's $.ajaxHow to await the ajax request?,使用jQuery's $.ajax執行async
  • 在try裡面,放入一般$.ajax抓取API資料的方式,如url、type、dataType
  • 首先,在連結的部分,我們希望每次抓取5筆資料,呈現1頁,所以在外面設置let limit = 5;let page = 1於url中加入該變數
  • 在抓取資料成功時,放入function,並用$.each來執行
    • $.each先傳入該資料(data)陣列,其function (index, value)放入索引以及值的內容。
    • 宣告postEl變數,創造名為postdiv=> $('\<div />')
    • 加入postclass
    • 加入html
    • 最後將此變數,放置呈現文章的容器postEl.appendTo('#posts-container');
let limit = 5
let page = 1

async function doAjax() {
  let result;

  try {
    result = await $.ajax({
      url: `https://jsonplaceholder.typicode.com/posts?_limit=${limit}&_page=${page}`,
      type: 'get',
      dataType: 'json',
      success: function (data) {
      
      $.each(data, function (index, value) {
          const postEl = $('<div />').addClass('post').html(`<div class="number">${value.id}</div> <div class="post-info"><h2 class="post-title">${value.title}</h2><p class="post-body">${value.body}</p>
      </div>`)
          //console.log(postEl)
          postEl.appendTo('#posts-container');
          //$('#posts-container').append(postEl)

        });

       
      }
    });

    return result;
  } catch (error) {
    console.error(error);
  }

}

doAjax();

查看是否有成功取得資料: console.log(data);

參考資料:
使用jQuery創造div
https://stackoverflow.com/questions/10402567/jquery-div-vs-div
jQuery.each()

3.Infinite Scroll無限捲動(瀑布流)

  • scrollTop網頁右邊的卷軸到最上端網頁的距離有多少
  • scrollHeight 取得整個沒被擋住的高、clientHeight 取得元素的高度(含padding 不含 border)
  • 完整內容高度 (scrollHeight) = 內容頂端與捲軸頂端的距離 (scrollTop) + 捲軸本身高度 (clientHeight) + 內容底端與捲軸底端的距離。

例子:

$(function () {
  $(window).scroll(function () {
    var scrollVal = $(this).scrollTop();
    $("span.qScrollTop").text(scrollVal);
  });
});

if(scrollVal > 500){
  /* 如果滾動的物件捲動 > 500 則觸發指定的動作。*/
}

  • 注意:window本身沒有scrollTop/Left這個屬性,所以window.scrollTop是undefined的
    所以可能要從body、document來取得

本段落語法:

  • 上述說明各視窗高度,在此if判斷式中scrollTop + clientHeight >= scrollHeight - 5來計算,當捲軸捲到該位置時,要呈現載入畫面
  • 接著根據載入畫面函式,來放入載入以及呈現接續畫面得設定
    • 使用setTimeout(),在1秒後消除載入圖示,接著在300毫秒後,馬上換頁執行載入新資料
$(window).scroll(function () {
  var scrollTop = $(this).scrollTop();
  var scrollHeight = $('body').prop("scrollHeight");
  //一樣 var scrollHeight2 = document.documentElement.scrollHeight;
  var clientHeight = document.documentElement.clientHeight;
  //https://stackoverflow.com/questions/10423759/plain-javascript-to-jquery-clientheight

  // console.log('scrollTop:', scrollTop);
  // console.log('scrollHeight:', scrollHeight);
  // console.log('clientHeight:', clientHeight);


  if (scrollTop + clientHeight >= scrollHeight - 5) {
    //console.log('show up 123')
    showLoading();
  }
})


//顯示載入圖示,並取得更多串接資料
function showLoading() {
  $('.loader').addClass('show');


  setTimeout(function () {

    $('.loader').removeClass('show');
    setTimeout(function () {
      page++;
      doAjax();
    }, 300);

  }, 1000);  //1秒之後消失

}

參考資料:
[筆記] 計算網頁底部位置,當網頁達到底部時才產生效果─jQuery
一次搞懂 clientHeight/scrollHeight/scrollTop的區別

4.篩選輸入框資料

  • 綁定事件為.keyup指放開鍵盤的那個剎那,觸發該事件
  • 執行的函式內容為:
    • var text取得輸入值並轉為小寫
    • 利用迴圈,去搜尋關鍵字,判斷,值轉為小寫文字的內容是否符合條件
    • -1 :意指條件不符合
    • indexOf() 方法用來判斷字串字串變數中是否包含某字串。
//輸入框搜尋//https://makitweb.com/jquery-search-text-in-the-element-with-contains-selector/  (=>Loop all .content )
  $('#filter').keyup(function () {

    // 輸入值的搜尋
    var text = $('#filter').val().toLowerCase();

    // 隱藏所有資料
    $('.post').hide();

    // 迴圈搜尋整個文件
    $('.post').each(function () {

      if ($(this).text().toLowerCase().indexOf("" + text + "") != -1) {
        $(this).closest('.post').show();
      }
    });

參考資料:
比較 keydown, keypress, keyup 的差異
jQuery – Search text in the Element with :contains() Selector
JavaScript String indexOf()


上一篇
[Day 27] JS實作練習 - Music Player
下一篇
[Day 29] JS 實作練習 - YouTube API
系列文
邊工作邊進行前端學習之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言